#ifndef _MSG_H_
#define _MSG_H_

#include <stdint.h>

#define OFFSETOF(type, memb)    ((int)(&(((type *)0)->memb)))

#define MSG_MAX_LEN			1<<20 /* 1M */
#define MSG_HEAD_LEN		12

#define MSG_IPADDR_SIZE		16	/*ipv4 only*/

typedef struct LOAD_PARAM {
	uint16_t 	ulen;		/* url len */
	uint16_t 	clen;		/* cookie len */
	char		*addr;
	char		*url;
	char		*cookie;
} LOAD_PARAM;

#pragma pack(1)
/* head of msg */
typedef struct MSG_HEAD {
	uint32_t	packlen;
	uint32_t	msgid;
	uint32_t	msgtype;
} MSG_HEAD;

/* request item, size = sizeof(MSG_LOAD_ITEM) - 1 + ulen + clen + (ulen + clen) % 2 */
typedef struct MSG_LOAD_ITEM {
	uint16_t 	ulen;		/* url len */
	uint16_t 	clen;		/* cookie len */
	char		addr[MSG_IPADDR_SIZE];
	char		vbuf[0];	/* variable buf of url and cookie, maybe pading */
} MSG_LOAD_ITEM;

typedef struct MSG_LOAD_REQ {
	uint16_t	num;		/* num of request item */
	char		vbuf[0];	/* variable buf of request item */
} MSG_LOAD_REQ;

/* more bodys ... */

#pragma pack(0)

enum STATUS{
	STAT_OK = 0,
	STAT_MSGTYPE_ERR,
	STAT_MSG_ERR,
	/* more */
};

enum MSGTYPE{
	TYPE_LOAD_REQ  = 0x00000001,
	TYPE_LOAD_RESP = 0x80000001,
	/* more */
};

//pack decode. return status code >= 0, <0 means malform, set headlen & packlen
int msg_depack(const char * buf, int buflen, int * headlenp, int * packlenp, int *scodep);
void msg_hex(const char * buf, int buflen);
char * msg_load_req_new(int * buflenp, int num, const LOAD_PARAM * params);

void msg_head_h2n(struct MSG_HEAD * head);
void msg_head_n2h(struct MSG_HEAD * head);
void msg_load_item_h2n(struct MSG_LOAD_ITEM * item);
void msg_load_item_n2h(struct MSG_LOAD_ITEM * item);
void msg_load_req_h2n(struct MSG_LOAD_REQ * body);
void msg_load_req_n2h(struct MSG_LOAD_REQ * body);

#endif

